/* 
 * File:   move.h
 * Author: tomas
 *
 * Created on March 28, 2009, 8:45 PM
 */

#pragma once
#ifndef _MOVE_H
#define _MOVE_H

#include <string>
#include <ostream>

#include <boost/serialization/access.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>

#include "horse.h"
#include "utils.h"


//V kodu spoleham na to, ze platne tahy maji cisla 1 az 8. Nemenit!
enum Direction {
	NONE, //nedoslo k pohybu..jezdec zustal na miste..
	RDD = 1,
	RRD,
	LLD,
	LDD,
	RRU,
	RUU,
	LUU,
	LLU = 8
};
std::string directionToString(Direction dir)
{
	switch (dir)
	{
	case NONE:
		return "NONE";
	case LLU:
		return "LLU";
	case LLD:
		return "LLD";
	case RRU:
		return "RRU";
	case RRD:
		return "RRD";
	case LUU:
		return "LUU";
	case LDD:
		return "LDD";
	case RUU:
		return "RUU";
	case RDD:
		return "RDD";
	default:
		throw "hapalo";
	}
	
}
struct Move {

	

	utils::coords_t origCoords;
	utils::coords_t targetCoords;
	Direction dir;

	//////////////////////////////////////////////////////////////////////////
	//Default Ctor. Vyprodukuje move se samymi nulami.
	Move() : dir(NONE), origCoords(0,0), targetCoords(0,0)
	{}

	//////////////////////////////////////////////////////////////////////////
	//Ctor.
	Move(const unsigned origX, const unsigned origY, const Direction _dir)
		: dir(_dir), origCoords(origX, origY)
	{
		targetCoords = makeMove(origCoords, _dir);
	}

	//////////////////////////////////////////////////////////////////////////
	//Ctor.
	Move(const utils::coords_t _c, const Direction _dir)
		: dir(_dir), origCoords(_c)
	{
		targetCoords = makeMove(_c, _dir);
	}

	bool operator==(const Move& that) const
	{
		if (this->dir!=that.dir)
		{
			return false;
		}
		if (this->origCoords!=that.origCoords || this->targetCoords!=that.targetCoords)
		{
			return false;
		}
		return true;
	}

	bool operator!=(const Move& that) const
	{
		return !(*this==that);
	}

	//////////////////////////////////////////////////////////////////////////
	//Printout
	friend std::ostream& operator<< (std::ostream& os, const Move& m)
	{
		using namespace utils;
		os << m.origCoords << "->" << m.targetCoords;
		
		return os;
	}

private:
	friend class boost::serialization::access;

	template<class Archive>
	inline void serialize( Archive & ar, const unsigned int version)
	{
		ar & origCoords & targetCoords & dir;
	}
	

	//////////////////////////////////////////////////////////////////////////
	//Pomocna metoda, vypocita cilove souradnice ze zadanych zdrojovych a zadaneho smeru.
	static utils::coords_t makeMove(const utils::coords_t &origCoords, const Direction & dir)
	{
		switch (dir)
		{
		case LLU:
			return utils::coords_t(origCoords.first-2,origCoords.second-1);

		case LLD:
			return utils::coords_t(origCoords.first-2,origCoords.second+1);

		case LUU:
			return utils::coords_t(origCoords.first-1,origCoords.second-2);

		case LDD:
			return utils::coords_t(origCoords.first-1,origCoords.second+2);

		case RRU:
			return utils::coords_t(origCoords.first+2,origCoords.second-1);

		case RRD:
			return utils::coords_t(origCoords.first+2,origCoords.second+1);
			
		case RUU:
			return utils::coords_t(origCoords.first+1,origCoords.second-2);
			
		case RDD:
			return utils::coords_t(origCoords.first+1,origCoords.second+2);
			
		default:
			throw "Neznamy smer.";
		}
	}
};

BOOST_IS_BITWISE_SERIALIZABLE(Move);


#endif	/* _MOVE_H */
